import("//compiler-rt/target.gni")

source_set("cxx_sources") {
  configs -= [ "//llvm/utils/gn/build:llvm_code" ]
  configs += [ "//llvm/utils/gn/build:crt_code" ]
  sources = [ "asan_new_delete.cpp" ]
}

if (current_os == "mac") {
  asan_target_type = "shared_library"
} else {
  asan_target_type = "static_library"
}

target(asan_target_type, "asan") {
  configs -= [ "//llvm/utils/gn/build:llvm_code" ]
  configs += [ "//llvm/utils/gn/build:crt_code" ]

  output_dir = crt_current_out_dir
  if (current_os == "mac") {
    output_name = "clang_rt.asan_osx_dynamic"
  } else {
    assert(current_os != "win", "FIXME")
    output_name = "clang_rt.asan$crt_current_target_suffix"
  }

  deps = [
    "//compiler-rt/lib/interception:sources",
    "//compiler-rt/lib/lsan:common_sources",
    "//compiler-rt/lib/sanitizer_common:sources",
    "//compiler-rt/lib/ubsan:sources",
  ]

  if (asan_target_type == "static_library") {
    complete_static_lib = true
    configs -= [ "//llvm/utils/gn/build:thin_archive" ]
    deps += [ ":asan_cxx" ]
  } else {
    deps += [
      ":cxx_sources",
      "//compiler-rt/lib/ubsan:cxx_sources",
    ]
    defines = [ "ASAN_DYNAMIC" ]
  }

  sources = [
    "asan_activation.cpp",
    "asan_activation.h",
    "asan_activation_flags.inc",
    "asan_allocator.cpp",
    "asan_allocator.h",
    "asan_debugging.cpp",
    "asan_descriptions.cpp",
    "asan_descriptions.h",
    "asan_errors.cpp",
    "asan_errors.h",
    "asan_fake_stack.cpp",
    "asan_fake_stack.h",
    "asan_flags.cpp",
    "asan_flags.h",
    "asan_flags.inc",
    "asan_fuchsia.cpp",
    "asan_globals.cpp",
    "asan_globals_win.cpp",
    "asan_init_version.h",
    "asan_interceptors.cpp",
    "asan_interceptors.h",
    "asan_interceptors_memintrinsics.cpp",
    "asan_interceptors_memintrinsics.h",
    "asan_interface.inc",
    "asan_interface_internal.h",
    "asan_internal.h",
    "asan_linux.cpp",
    "asan_lock.h",
    "asan_mac.cpp",
    "asan_malloc_linux.cpp",
    "asan_malloc_mac.cpp",
    "asan_malloc_win.cpp",
    "asan_mapping.h",
    "asan_memory_profile.cpp",
    "asan_poisoning.cpp",
    "asan_poisoning.h",
    "asan_posix.cpp",
    "asan_premap_shadow.cpp",
    "asan_premap_shadow.h",
    "asan_report.cpp",
    "asan_report.h",
    "asan_rtl.cpp",
    "asan_scariness_score.h",
    "asan_shadow_setup.cpp",
    "asan_stack.cpp",
    "asan_stack.h",
    "asan_stats.cpp",
    "asan_stats.h",
    "asan_suppressions.cpp",
    "asan_suppressions.h",
    "asan_thread.cpp",
    "asan_thread.h",
    "asan_win.cpp",
  ]
  if (target_os != "mac" && target_os != "win") {
    sources += [ "asan_interceptors_vfork.S" ]
  }

  # To be able to include sanitizer_common.
  include_dirs = [ ".." ]

  # FIXME: have SANITIZER_COMMON_CFLAGS thingy? should fno-builtin be in
  # crt_code?
  cflags = [ "-fno-builtin" ]
  if (target_os != "win") {
    cflags += [ "-ftls-model=initial-exec" ]
  }

  # FIXME: link rt dl m pthread log
  # FIXME: dep on libcxx-headers?
  # FIXME: add_sanitizer_rt_version_list (cf hwasan)
  # FIXME: need libclang_rt.asan*.a.syms?
  # FIXME: windows flags (-Zl -nodefaultlibs)
  # FIXME: asan_ignorelist.txt

  if (target_os == "android") {
    ldflags = [ "-Wl,-z,global" ]
  }

  if (target_os == "mac") {
    # The -U flags below correspond to the add_weak_symbols() calls in CMake.
    ldflags = [
      "-lc++",
      "-lc++abi",

      # asan
      "-Wl,-U,___asan_default_options",
      "-Wl,-U,___asan_default_suppressions",
      "-Wl,-U,___asan_on_error",
      "-Wl,-U,___asan_set_shadow_00",
      "-Wl,-U,___asan_set_shadow_f1",
      "-Wl,-U,___asan_set_shadow_f2",
      "-Wl,-U,___asan_set_shadow_f3",
      "-Wl,-U,___asan_set_shadow_f4",
      "-Wl,-U,___asan_set_shadow_f5",
      "-Wl,-U,___asan_set_shadow_f6",
      "-Wl,-U,___asan_set_shadow_f7",
      "-Wl,-U,___asan_set_shadow_f8",

      # lsan
      "-Wl,-U,___lsan_default_options",
      "-Wl,-U,___lsan_default_suppressions",
      "-Wl,-U,___lsan_is_turned_off",

      # ubsan
      "-Wl,-U,___ubsan_default_options",

      # sanitizer_common
      "-Wl,-U,___sanitizer_free_hook",
      "-Wl,-U,___sanitizer_malloc_hook",
      "-Wl,-U,___sanitizer_report_error_summary",
      "-Wl,-U,___sanitizer_sandbox_on_notify",
      "-Wl,-U,___sanitizer_symbolize_code",
      "-Wl,-U,___sanitizer_symbolize_data",
      "-Wl,-U,___sanitizer_symbolize_demangle",
      "-Wl,-U,___sanitizer_symbolize_flush",

      # xray
      "-Wl,-U,___start_xray_fn_idx",
      "-Wl,-U,___start_xray_instr_map",
      "-Wl,-U,___stop_xray_fn_idx",
      "-Wl,-U,___stop_xray_instr_map",

      # FIXME: better
      "-Wl,-install_name,@rpath/libclang_rt.asan_osx_dynamic.dylib",
    ]
    # FIXME: -Wl,-rpath
    # FIXME: codesign (??)
  }
}

if (asan_target_type == "static_library") {
  static_library("asan_cxx") {
    assert(current_os != "win", "FIXME")
    output_dir = crt_current_out_dir
    output_name = "clang_rt.asan_cxx$crt_current_target_suffix"
    complete_static_lib = true
    configs -= [ "//llvm/utils/gn/build:thin_archive" ]
    deps = [
      ":cxx_sources",
      "//compiler-rt/lib/ubsan:cxx_sources",
    ]
  }
}

# FIXME: Move these to real targets.
source_set("unused") {
  sources = [
    "asan_preinit.cpp",
    "asan_win_dll_thunk.cpp",
    "asan_win_dynamic_runtime_thunk.cpp",
  ]
}
